// Copyright 2007, 2008 The Apache Software Foundation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package com.cie2.janji.services;

import java.io.IOException;

import org.apache.tapestry5.SymbolConstants;
import org.apache.tapestry5.ioc.Configuration;
import org.apache.tapestry5.ioc.MappedConfiguration;
import org.apache.tapestry5.ioc.OrderedConfiguration;
import org.apache.tapestry5.ioc.Resource;
import org.apache.tapestry5.ioc.ServiceBinder;
import org.apache.tapestry5.ioc.annotations.InjectService;
import org.apache.tapestry5.ioc.internal.util.ClasspathResource;
import org.apache.tapestry5.services.Request;
import org.apache.tapestry5.services.RequestFilter;
import org.apache.tapestry5.services.RequestHandler;
import org.apache.tapestry5.services.Response;
import org.apache.tapestry5.upload.services.UploadSymbols;
import org.chenillekit.quartz.services.JobSchedulingBundle;
import org.slf4j.Logger;


/**
 * This module is automatically included as part of the Tapestry IoC Registry, it's a good place to
 * configure and extend Tapestry, or to place your own service definitions.
 */
public class AppModule
{
    public static void bind(ServiceBinder binder)
    {
    	binder.bind(LayoutInfoNotifier.class);
    	binder.bind(LoginService.class);
    	binder.bind(UserManagement.class);
    	binder.bind(BaseEntityService.class);
    	binder.bind(PromiseService.class);
    	binder.bind(ArticleService.class);
    	binder.bind(PromiseStatisticsService.class);
    	binder.bind(CategoryService.class);
    	binder.bind(PromiseEngine.class);
    	binder.bind(EntityRoleService.class);
    	binder.bind(EntityRoleInTimeService.class);
    	binder.bind(UpdatePromiseJob.class);

    	binder.bind(PromiseStatusUIHelper.class);

    	
//    	binder.bind(TaskDAO.class, TaskDAOImpl.class);
        
        // Make bind() calls on the binder object to define most IoC services.
        // Use service builder methods (example below) when the implementation
        // is provided inline, or requires more initialization than simply
        // invoking the constructor.
    }
    


    public static void contributeApplicationDefaults(
            MappedConfiguration<String, String> configuration)
    {
        // Contributions to ApplicationDefaults will override any contributions to
        // FactoryDefaults (with the same key). Here we're restricting the supported
        // locales to just "en" (English). As you add localised message catalogs and other assets,
        // you can extend this list of locales (it's a comma seperated series of locale names;
        // the first locale name is the default when there's no reasonable match).
        
        configuration.add(SymbolConstants.SUPPORTED_LOCALES, "en");

        // The factory default is true but during the early stages of an application
        // overriding to false is a good idea. In addition, this is often overridden
        // on the command line as -Dtapestry.production-mode=false
        configuration.add(SymbolConstants.PRODUCTION_MODE, "false");
        
        // settinf upload file max to 200KB
        configuration.add(UploadSymbols.FILESIZE_MAX, "204800"); 
    }

    // contribute for changing the default package where hibernate will look for your
    // entities
    public static void contributeHibernateEntityPackageManager(Configuration<String> configuration)
    {
////        configuration.add("your.appl.package.entities");
    	configuration.add("com.cie2.janji.entities");
    }
    
    
    //contribute for quartz
	public static void contributeSchedulerFactory(MappedConfiguration<String, Resource> configuration)
	{
	    Resource configResource = new ClasspathResource("quartz.properties");
	    configuration.add("quartz.properties", configResource);
	}

    
	public static void contributeQuartzSchedulerManager(
			OrderedConfiguration<JobSchedulingBundle> configuration,
			UpdatePromiseJob updatePromiseJob, PromiseEngine promiseEngine) {
		configuration.add("promiseScheduler", new PromiseSchedulerBundle(updatePromiseJob, promiseEngine));
	}
	
    // end quartz
    		       
    /**
	 * This is a service definition, the service will be named "TimingFilter".
	 * The interface, RequestFilter, is used within the RequestHandler service
	 * pipeline, which is built from the RequestHandler service configuration.
	 * Tapestry IoC is responsible for passing in an appropriate Log instance.
	 * Requests for static resources are handled at a higher level, so this
	 * filter will only be invoked for Tapestry related requests.
	 * 
	 * <p>
	 * Service builder methods are useful when the implementation is inline as
	 * an inner class (as here) or require some other kind of special
	 * initialization. In most cases, use the static bind() method instead.
	 * 
	 * <p>
	 * If this method was named "build", then the service id would be taken from
	 * the service interface and would be "RequestFilter". Since Tapestry
	 * already defines a service named "RequestFilter" we use an explicit
	 * service id that we can reference inside the contribution method.
	 */    
    public RequestFilter buildTimingFilter(final Logger log)
    {
        return new RequestFilter()
        {
            public boolean service(Request request, Response response, RequestHandler handler)
                    throws IOException
            {
                long startTime = System.currentTimeMillis();

                try
                {
                    // The reponsibility of a filter is to invoke the corresponding method
                    // in the handler. When you chain multiple filters together, each filter
                    // received a handler that is a bridge to the next filter.
                    
                    return handler.service(request, response);
                }
                finally
                {
                    long elapsed = System.currentTimeMillis() - startTime;

                    log.info(String.format("Request time: %d ms", elapsed));
                }
            }
        };
    }

    /**
     * This is a contribution to the RequestHandler service configuration. This is how we extend
     * Tapestry using the timing filter. A common use for this kind of filter is transaction
     * management or security.
     */
    public void contributeRequestHandler(OrderedConfiguration<RequestFilter> configuration,
            @InjectService("TimingFilter")
            RequestFilter filter)
    {
        // Each contribution to an ordered configuration has a name, When necessary, you may
        // set constraints to precisely control the invocation order of the contributed filter
        // within the pipeline.
        
        configuration.add("Timing", filter);
    }
}
